// 格式转换器 - 在不同脚本格式间转换
import { parsePlaywrightScript } from './playwrightParser.js'

/**
 * 脚本格式转换器
 */
export class FormatConverter {
  /**
   * 检测脚本格式
   * @param {string} script - 脚本内容
   * @returns {string} - 'playwright' 或 'jsonl' 或 'unknown'
   */
  static detectFormat(script) {
    if (!script || typeof script !== 'string') {
      return 'unknown'
    }

    // 去除空白行和注释
    const trimmedScript = script.trim()
    
    // 首先检查是否包含元数据标记，这是我们转换后添加的
    if (trimmedScript.includes('"type":"metadata"') && 
        trimmedScript.includes('"format":"playwright"') && 
        trimmedScript.includes('"originalScript"')) {
      return 'jsonl'
    }
    
    // 检测是否为JSONL格式 (每行一个JSON对象)
    if (trimmedScript.startsWith('{') && /\}\s*\n\s*\{/.test(trimmedScript)) {
      try {
        // 尝试解析第一行作为JSON
        const firstLine = trimmedScript.split('\n')[0]
        JSON.parse(firstLine)
        return 'jsonl'
      } catch (e) {
        // 解析失败，可能不是JSONL
      }
    }

    // 检测是否为Playwright格式 - 更全面的检查
    const playwrightPatterns = [
      // 导入语句
      /import\s+.*?playwright/i,
      /import\s+.*?test.*?from/i,
      /import\s+.*?expect.*?from/i,
      
      // 测试定义
      /test\s*\(\s*['"].*?['"]/i,
      /describe\s*\(\s*['"].*?['"]/i,
      
      // 常见的Playwright API调用
      /page\.goto\s*\(/i,
      /page\.click\s*\(/i,
      /page\.fill\s*\(/i,
      /page\.type\s*\(/i,
      /page\.waitForSelector\s*\(/i,
      /expect\s*\(\s*page/i,
      /page\.locator\s*\(/i
    ]
    
    // 检查是否匹配Playwright模式
    const playwrightMatches = playwrightPatterns.filter(pattern => pattern.test(trimmedScript))
    
    // 如果匹配了多个Playwright模式，很可能是Playwright脚本
    if (playwrightMatches.length >= 2 && trimmedScript.includes('async') && trimmedScript.includes('page')) {
      return 'playwright'
    }

    // 进一步检查JSONL格式 - 更严格的验证
    try {
      const lines = trimmedScript.split('\n').filter(line => line.trim())
      
      // 如果没有内容，返回未知
      if (lines.length === 0) {
        return 'unknown'
      }
      
      // 检查每一行是否都是有效的JSON
      let validJsonLines = 0
      let invalidLines = 0
      
      for (const line of lines) {
        if (line.trim()) {
          try {
            const parsed = JSON.parse(line)
            // 检查是否包含常见的步骤类型字段
            if (typeof parsed === 'object' && parsed.type) {
              validJsonLines++
            }
          } catch (e) {
            invalidLines++
          }
        }
      }
      
      // 如果大部分行都是有效的JSON，且至少有一行，则认为是JSONL
      if (validJsonLines > 0 && validJsonLines > invalidLines) {
        return 'jsonl'
      }
    } catch (e) {
      // 不是有效的JSONL
    }

    return 'unknown'
  }

  /**
   * Playwright 转 JSONL
   * @param {string} playwrightScript - Playwright脚本内容
   * @returns {string} JSONL格式字符串
   */
  static playwrightToJsonl(playwrightScript) {
    try {
      // 提取操作步骤
      const steps = []
      const lines = playwrightScript.split('\n')
      
      // 保存原始脚本，以便在转换回来时可以恢复
      steps.push({
        type: 'metadata',
        originalScript: playwrightScript,
        format: 'playwright'
      })
      
      // 提取测试名称
      const testNameMatch = playwrightScript.match(/test\(['"](.*?)['"],/)
      const testName = testNameMatch ? testNameMatch[1] : 'converted_test'
      
      // 查找常见的Playwright操作
      for (let i = 0; i < lines.length; i++) {
        const line = lines[i].trim()
        
        // 导航到URL
        const gotoMatch = line.match(/await\s+page\.goto\(['"]([^'"]+)['"](?:,\s*({[^}]+}))?\)/)
        if (gotoMatch) {
          steps.push({
            type: 'navigation',
            url: gotoMatch[1],
            options: gotoMatch[2] || null,
            originalCode: line
          })
          continue
        }
        
        // 填写表单 - 支持更多格式
        const fillMatch = line.match(/await\s+page\.(?:fill|type)\(['"]([^'"]+)['"],\s*['"]([^'"]+)['"](?:,\s*({[^}]+}))?\)/)
        if (fillMatch) {
          steps.push({
            type: 'input',
            selector: fillMatch[1],
            value: fillMatch[2],
            options: fillMatch[3] || null,
            method: line.includes('.fill') ? 'fill' : 'type',
            originalCode: line
          })
          continue
        }
        
        // 点击元素 - 支持更多格式
        const clickMatch = line.match(/await\s+page\.(?:click|tap|dblclick)\(['"]([^'"]+)['"](?:,\s*({[^}]+}))?\)/)
        if (clickMatch) {
          steps.push({
            type: 'click',
            selector: clickMatch[1],
            options: clickMatch[2] || null,
            method: line.includes('.click') ? 'click' : 
                    line.includes('.dblclick') ? 'dblclick' : 'tap',
            originalCode: line
          })
          continue
        }
        
        // 等待元素可见
        const waitForSelectorMatch = line.match(/await\s+page\.waitForSelector\(['"]([^'"]+)['"](?:,\s*({[^}]+}))?\)/)
        if (waitForSelectorMatch) {
          const options = waitForSelectorMatch[2] || null
          const condition = options && options.includes('state: "visible"') ? 'visible' : 
                           options && options.includes('state: "hidden"') ? 'hidden' : 'visible'
          
          steps.push({
            type: 'wait',
            selector: waitForSelectorMatch[1],
            condition: condition,
            options: options,
            originalCode: line
          })
          continue
        }
        
        // 等待超时
        const waitForTimeoutMatch = line.match(/await\s+page\.waitForTimeout\((\d+)\)/)
        if (waitForTimeoutMatch) {
          steps.push({
            type: 'wait',
            timeout: parseInt(waitForTimeoutMatch[1]),
            originalCode: line
          })
          continue
        }
        
        // 断言元素可见
        const expectVisibleMatch = line.match(/await\s+expect\(page\.locator\(['"]([^'"]+)['"]\)\)\.toBeVisible\(/)
        if (expectVisibleMatch) {
          steps.push({
            type: 'assertion',
            selector: expectVisibleMatch[1],
            assertion: 'visible',
            originalCode: line
          })
          continue
        }
        
        // 断言元素包含文本
        const expectTextMatch = line.match(/await\s+expect\(page\.locator\(['"]([^'"]+)['"]\)\)\.toHaveText\(['"]([^'"]+)['"]/);
        if (expectTextMatch) {
          steps.push({
            type: 'assertion',
            selector: expectTextMatch[1],
            assertion: 'text',
            expectedValue: expectTextMatch[2],
            originalCode: line
          })
          continue
        }
        
        // 截图
        const screenshotMatch = line.match(/await\s+page\.screenshot\(({[^}]+})\)/)
        if (screenshotMatch) {
          const optionsStr = screenshotMatch[1]
          const filenameMatch = optionsStr.match(/path:\s*['"]([^'"]+)['"]/);
          const filename = filenameMatch ? filenameMatch[1] : 'screenshot.png'
          
          steps.push({
            type: 'screenshot',
            filename: filename,
            options: optionsStr,
            originalCode: line
          })
          continue
        }
        
        // 注释行
        if (line.startsWith('//') && line.length > 2) {
          steps.push({
            type: 'comment',
            text: line.substring(2).trim(),
            originalCode: line
          })
          continue
        }
      }
      
      // 转换为JSONL格式
      return steps.map(step => JSON.stringify(step)).join('\n')
    } catch (error) {
      throw new Error(`Playwright转JSONL失败: ${error.message}`)
    }
  }

  /**
   * JSONL 转 Playwright
   * @param {string} jsonlContent - JSONL格式内容
   * @param {string} testName - 测试名称
   * @returns {string} Playwright脚本
   */
  static jsonlToPlaywright(jsonlContent, testName = 'test') {
    try {
      // 解析JSONL
      const lines = jsonlContent.split('\n').filter(line => line.trim())
      const steps = lines.map(line => JSON.parse(line))
      
      // 检查是否有元数据，如果有，可以直接恢复原始脚本
      const metadataStep = steps.find(step => step.type === 'metadata' && step.format === 'playwright')
      if (metadataStep && metadataStep.originalScript) {
        return metadataStep.originalScript
      }
      
      // 如果没有元数据，则根据步骤重新生成Playwright脚本
      // 提取测试名称（如果有）
      const testNameStep = steps.find(step => step.testName)
      const finalTestName = testNameStep ? testNameStep.testName : testName
      
      // 生成Playwright脚本
      let playwrightCode = `import { test, expect } from '@playwright/test';\n\n`
      playwrightCode += `test('${finalTestName}', async ({ page }) => {\n`
      
      // 添加每个步骤的代码
      for (const step of steps) {
        // 如果步骤有原始代码，直接使用
        if (step.originalCode && step.type !== 'metadata') {
          playwrightCode += `  ${step.originalCode}\n\n`
          continue
        }
        
        switch (step.type) {
          case 'navigation':
            playwrightCode += `  // 打开网页\n`
            if (step.options) {
              playwrightCode += `  await page.goto('${step.url}', ${step.options});\n`
            } else {
              playwrightCode += `  await page.goto('${step.url}');\n`
            }
            break
            
          case 'input':
            playwrightCode += `  // 输入文本\n`
            const inputMethod = step.method || 'fill'
            if (step.options) {
              playwrightCode += `  await page.${inputMethod}('${step.selector}', '${step.value}', ${step.options});\n`
            } else {
              playwrightCode += `  await page.${inputMethod}('${step.selector}', '${step.value}');\n`
            }
            break
            
          case 'click':
            playwrightCode += `  // 点击元素\n`
            const clickMethod = step.method || 'click'
            if (step.options) {
              playwrightCode += `  await page.${clickMethod}('${step.selector}', ${step.options});\n`
            } else {
              playwrightCode += `  await page.${clickMethod}('${step.selector}');\n`
            }
            break
            
          case 'wait':
            playwrightCode += `  // 等待元素\n`
            if (step.timeout !== undefined) {
              playwrightCode += `  await page.waitForTimeout(${step.timeout});\n`
            } else if (step.options) {
              playwrightCode += `  await page.waitForSelector('${step.selector}', ${step.options});\n`
            } else {
              playwrightCode += `  await page.waitForSelector('${step.selector}');\n`
            }
            break
            
          case 'assertion':
            playwrightCode += `  // 验证断言\n`
            if (step.assertion === 'visible') {
              playwrightCode += `  await expect(page.locator('${step.selector}')).toBeVisible();\n`
            } else if (step.assertion === 'text') {
              playwrightCode += `  await expect(page.locator('${step.selector}')).toHaveText('${step.expectedValue}');\n`
            }
            break
            
          case 'screenshot':
            playwrightCode += `  // 截图\n`
            if (step.options) {
              playwrightCode += `  await page.screenshot(${step.options});\n`
            } else {
              playwrightCode += `  await page.screenshot({ path: '${step.filename || 'screenshot.png'}' });\n`
            }
            break
            
          case 'comment':
            playwrightCode += `  // ${step.text}\n`
            break
            
          default:
            if (step.originalCode) {
              playwrightCode += `  ${step.originalCode}\n`
            } else {
              playwrightCode += `  // ${step.description || '未知操作'}\n`
            }
        }
        
        playwrightCode += `\n`
      }
      
      playwrightCode += `});`
      return playwrightCode
      
    } catch (error) {
      console.error('转换JSONL到Playwright失败:', error)
      return '// 转换失败，请检查JSONL格式是否正确'
    }
  }

  /**
   * 解析JSONL格式内容
   * @param {string} jsonlContent - JSONL内容
   * @returns {Array} 步骤数组
   */
  static parseJsonl(jsonlContent) {
    const steps = []
    const lines = jsonlContent.split('\n').filter(line => line.trim())
    
    for (let i = 0; i < lines.length; i++) {
      try {
        const step = JSON.parse(lines[i])
        steps.push({
          stepNumber: step.stepNumber || (i + 1),
          type: step.type || 'unknown',
          action: step.action || '',
          description: step.description || '',
          selector: step.selector || '',
          value: step.value || '',
          url: step.url || '',
          timeout: step.timeout || 0,
          assertion: step.assertion || '',
          expected: step.expected || '',
          filename: step.filename || '',
          originalCode: step.originalCode || '',
          timestamp: step.timestamp || new Date().toISOString()
        })
      } catch (error) {
        console.warn(`解析JSONL第${i + 1}行失败:`, lines[i], error)
      }
    }
    
    return steps
  }

  /**
   * 生成JSONL格式内容
   * @param {Array} steps - 步骤数组
   * @returns {string} JSONL格式字符串
   */
  static generateJsonl(steps) {
    return steps.map(step => JSON.stringify({
      stepNumber: step.stepNumber,
      type: step.type,
      action: step.action,
      description: step.description,
      selector: step.selector,
      value: step.value,
      url: step.url,
      timeout: step.timeout,
      assertion: step.assertion,
      expected: step.expected,
      filename: step.filename,
      originalCode: step.originalCode,
      timestamp: step.timestamp || new Date().toISOString()
    })).join('\n')
  }

  /**
   * 转换脚本格式
   * @param {string} script - 脚本内容
   * @param {string} targetFormat - 目标格式 ('playwright' 或 'jsonl')
   * @returns {string} - 转换后的脚本
   */
  static convertFormat(script, targetFormat) {
    try {
      // 验证输入
      if (!script || typeof script !== 'string') {
        return '// 错误：输入脚本不能为空'
      }
      
      if (targetFormat !== 'playwright' && targetFormat !== 'jsonl') {
        return `// 错误：不支持的目标格式 "${targetFormat}"，仅支持 'playwright' 或 'jsonl'`
      }
      
      // 检测源格式
      const sourceFormat = this.detectFormat(script)
      
      if (sourceFormat === 'unknown') {
        return '// 无法识别脚本格式，请检查输入是否为有效的 Playwright 或 JSONL 格式'
      }
      
      if (sourceFormat === targetFormat) {
        return script // 已经是目标格式，无需转换
      }
      
      let result
      
      // 执行转换
      if (sourceFormat === 'playwright' && targetFormat === 'jsonl') {
        result = this.playwrightToJsonl(script)
      } else if (sourceFormat === 'jsonl' && targetFormat === 'playwright') {
        result = this.jsonlToPlaywright(script)
      } else {
        return '// 不支持的转换格式'
      }
      
      // 验证转换结果
      if (!result || result.trim() === '') {
        return `// 转换失败：从 ${sourceFormat} 到 ${targetFormat} 的转换结果为空`
      }
      
      // 验证转换后的格式是否正确
      const resultFormat = this.detectFormat(result)
      if (resultFormat !== targetFormat && resultFormat !== 'unknown') {
        console.warn(`警告：转换结果格式检测为 ${resultFormat}，而非预期的 ${targetFormat}`)
      }
      
      return result
    } catch (error) {
      console.error('转换格式时发生错误:', error)
      return `// 转换过程中发生错误: ${error.message}`
    }
  }

  /**
   * 智能转换格式
   * @param {string} content - 输入内容
   * @param {string} targetFormat - 目标格式: 'playwright' | 'jsonl'
   * @param {Object} options - 转换选项
   * @returns {string} 转换后的内容
   */
  static smartConvert(content, targetFormat, options = {}) {
    const sourceFormat = this.detectFormat(content)
    
    if (sourceFormat === 'unknown') {
      throw new Error('无法识别的脚本格式')
    }
    
    if (sourceFormat === targetFormat) {
      return content // 已经是目标格式
    }
    
    const testName = options.testName || 'converted_test'
    
    switch (`${sourceFormat}_to_${targetFormat}`) {
      case 'playwright_to_jsonl':
        return this.playwrightToJsonl(content)
      
      case 'jsonl_to_playwright':
        return this.jsonlToPlaywright(content, testName)
      
      default:
        throw new Error(`不支持从 ${sourceFormat} 转换到 ${targetFormat}`)
    }
  }

  /**
   * 验证脚本格式
   * @param {string} content - 脚本内容
   * @param {string} expectedFormat - 期望格式
   * @returns {boolean} 是否符合期望格式
   */
  static validateFormat(content, expectedFormat) {
    const detectedFormat = this.detectFormat(content)
    return detectedFormat === expectedFormat
  }

  /**
   * 格式化输出选项
   * @param {string} content - 内容
   * @param {Object} options - 格式化选项
   * @returns {string} 格式化后的内容
   */
  static formatOutput(content, options = {}) {
    const {
      pretty = true,
      indent = 2,
      includeComments = false
    } = options
    
    if (!pretty) {
      return content
    }
    
    // 如果是JSON格式，进行美化
    try {
      const lines = content.split('\n')
      const formattedLines = lines.map(line => {
        if (line.trim()) {
          const obj = JSON.parse(line)
          return JSON.stringify(obj, null, indent)
        }
        return line
      })
      
      let result = formattedLines.join('\n')
      
      // 添加注释
      if (includeComments) {
        result = `// 自动生成的脚本文件\n// 生成时间: ${new Date().toLocaleString()}\n\n${result}`
      }
      
      return result
    } catch {
      // 不是JSON格式，返回原内容
      return content
    }
  }
}

// 导出便捷方法
export const {
  playwrightToJsonl,
  jsonlToPlaywright,
  parseJsonl,
  generateJsonl,
  detectFormat,
  smartConvert,
  validateFormat,
  formatOutput,
  convertFormat
} = FormatConverter

// 导出默认的转换函数
export { FormatConverter as default }
